// my-vuex.js
let Vue

class Store {
  constructor(options) {
    // 保存所有 mutation、action、getter 的容器
    this._mutations = Object.create(null)
    this._actions = Object.create(null)
    this._wrappedGetters = Object.create(null)
    this.getters = {}
    this.strict = options.strict || false
    this._commiting = false
    // 插件支持
    this._subscribers = []

    // 取出所有模块定义（包括根模块）
    this._modules = options.modules || {}

    // 安装模块并构建出完整的状态树
    const rootState = this.installModules(this, options)
    console.log('rootState', rootState)
    // 用 Vue 来创建响应式 state
    this._vm = new Vue({
      data: {
        $$state: rootState // 用 $$state 避免和用户使用的变量冲突
      }
    })

    // 执行 plugins
    const plugins = options.plugins || []
    plugins.forEach(plugin => plugin(this))

    // 确保 commit/dispatch 的 this 是 store 实例
    this.commit = this.commit.bind(this)
    this.dispatch = this.dispatch.bind(this)
    
    // 开启严格模式监听
    if (this.strict) {
      this.enableStrictMode()
    }
  }

  // 外部访问 state
  get state() {
    return this._vm._data.$$state
  }

  enableStrictMode() {
    this._vm.$watch(
      () => this._vm._data.$$state, // 1. 监听 state
      () => {
        // 2. 如果 state 被改了，就执行这个回调
        if (!this._commiting) {
          console.error(
            '[vuex-mini] Do not mutate state outside mutation handlers.'
          );
        }
      },
      { deep: true, async: true }      // 4. 深度监听 + 同步触发
    )
  }
  _withCommit(fn) {
    const prev = this._commiting
    this._commiting = true
    fn()
    this._commiting = prev
  }
  // 替换整个 state（例如持久化恢复）
  replaceState(newState) {
    this._withCommit(() => {
      const oldState = this._vm._data.$$state
      Object.keys(oldState).forEach(key => {
        Vue.delete(oldState, key)
      })
      Object.keys(newState).forEach(key => {
        Vue.set(oldState, key, newState[key])
      })
    })
  }

  // 提交 mutation（可能对应多个同名 mutation）
  commit(type, payload) {
    const entry = this._mutations[type]
    console.log('entry', entry)
    if (!entry) {
      console.warn(`[Vuex] unknown mutation type: ${type}`)
      return
    }
    this._withCommit(() => {
        entry.forEach(fn => fn(payload))
    })
    // 通知插件订阅者
    this._subscribers.forEach(sub => sub({ type, payload }, this.state))
  }

  // 分发 action（支持异步）
  dispatch(type, payload) {
    const entry = this._actions[type]
    if (!entry) {
      console.warn(`[Vuex] unknown action type: ${type}`)
      return
    }
    // 支持返回 Promise.all
    return Promise.all(entry.map(fn => fn(payload)))
  }

  // 订阅 mutation（插件用）
  subscribe(fn) {
    this._subscribers.push(fn)
  }

  // 安装模块并构建 state 树，同时注册对应的 mutations/actions/getters
  installModules(store, rootOptions) {
    const rootState = rootOptions.state || {}
    const register = (path, module) => {
      const isRoot = path.length === 0

      // 生成模块的命名空间，例如 ['user'] -> 'user/'
      const namespace = path.reduce((ns, key) => ns + key + '/', '')
      console.log('namespace', namespace)
      // 非根模块需要挂到父模块 state 上（响应式）
      if (!isRoot) {
        const parentState = path.slice(0, -1).reduce((state, key) => state[key], rootState)
        Vue.set(parentState, path[path.length - 1], module.state)
      }

      // 注册 mutations：命名空间 + key
      if (module.mutations) {
        Object.keys(module.mutations).forEach(key => {
          const type = namespace + key
          const fn = module.mutations[key]
          this._mutations[type] = this._mutations[type] || []
          this._mutations[type].push(payload => {
            const moduleState = path.reduce((s, k) => s[k], store.state)
            fn(moduleState, payload)
          })
        })
      }

      // 注册 actions
      if (module.actions) {
        Object.keys(module.actions).forEach(key => {
          const type = namespace + key
          const fn = module.actions[key]
          this._actions[type] = this._actions[type] || []
          this._actions[type].push(payload => {
            const moduleState = path.reduce((s, k) => s[k], store.state)
            return fn({
              state: moduleState,
              commit: store.commit,
              dispatch: store.dispatch
            }, payload)
          })
        })
      }

      // 注册 getters
      if (module.getters) {
        Object.keys(module.getters).forEach(key => {
          const type = namespace + key
          const fn = module.getters[key]
          this._wrappedGetters[type] = () => {
            const moduleState = path.reduce((s, k) => s[k], store.state)
            return fn(moduleState)
          }
        })
      }

      // 递归注册子模块
      if (module.modules) {
        Object.keys(module.modules).forEach(childKey => {
          register(path.concat(childKey), module.modules[childKey])
        })
      }
    }

    // 注册根模块
    register([], {
      state: rootOptions.state || {},
      mutations: rootOptions.mutations || {},
      actions: rootOptions.actions || {},
      getters: rootOptions.getters || {},
      modules: rootOptions.modules || {}
    })

    console.log('this._wrappedGetters', this._wrappedGetters)
    // 初始化 getter：将 wrappedGetter 转为计算属性
    // store.getters.doubleCount
    Object.keys(this._wrappedGetters).forEach(key => {
      Object.defineProperty(this.getters, key, {
        get: this._wrappedGetters[key],
        enumerable: true
      })
    })

    return rootState
  }
}

// Vue 插件安装入口
function install(_Vue) {
  Vue = _Vue
  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$MyStore = this.$options.MyStore
      }
    }
  })
}

export default {
  Store,
  install
}
